package com.chushouya.manager.service.admin.impl;


import com.chushouya.manager.dto.admin.user.*;
import com.chushouya.manager.service.admin.*;
import com.general.framework.core.enums.DelFlagEnum;
import com.general.framework.core.lang.*;
import com.chushouya.common.constant.SystemConfigEnum;
import com.chushouya.common.support.Contexts;
import com.chushouya.common.util.PasswordUtil;
import com.chushouya.manager.config.BizConfigEnum;
import com.chushouya.manager.dao.entity.AdminUserEntity;
import com.chushouya.manager.dao.repository.AdminUserRepository;
import com.chushouya.manager.dto.admin.dept.DeptListDTO;
import com.chushouya.manager.dto.admin.dept.DeptListQuery;
import com.chushouya.manager.dto.admin.user.*;
import com.chushouya.manager.dto.admin.userrole.UserRoleDTO;
import com.general.framework.core.enums.ContextUserType;
import com.general.framework.core.enums.StatusEnum;
import com.general.framework.core.exception.Ex;
import com.general.framework.core.schema.PageResult;
import com.chushouya.manager.service.admin.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户业务
 */
@Service
@Slf4j
@RefreshScope
public class AdminUserServiceImpl implements AdminUserService {

    @Resource
    private AdminUserRepository adminUserRepository;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private AdminTokenService adminTokenService;

    @Resource
    private ConfigService configService;

    @Resource
    private DeptService deptService;


    @PostConstruct
    public void init() {
        // 初始化超级管理员
        final String adminUserName = "admin";
        AdminUserEntity superAdmin = this.selectUserName(ContextUserType.ADMIN_PLATFORM.value(), adminUserName);
        if (Objects.isNull(superAdmin)) {
            log.info("===== CAN NOT FIND ADMIN USER, SYSTEM BEGIN INIT =====");
            superAdmin = new AdminUserEntity();
            superAdmin.setUserName(adminUserName);
            superAdmin.setNickName("超级管理员");
            // set password
            String defaultPassword = configService.selectConfigByKey(SystemConfigEnum.ADMIN_USER_DEFAULT_PASSWORD.getConfigKey()).getConfigValue();
            superAdmin.setPassword(PasswordUtil.encryptPassword(defaultPassword));
            superAdmin.setIsDefaultPassword(Boolean.TRUE);
            superAdmin.setUserType(ContextUserType.ADMIN_PLATFORM.value());
            superAdmin.setEmail("");
            superAdmin.setPhoneNumber("");
            superAdmin.setSex(Numbers.INTEGER_TWO);
            superAdmin.setAvatar("");
            superAdmin.setStatus(StatusEnum.normal.value());
            superAdmin.setRemark("超级管理员为系统内置用户,不可删除");
            superAdmin.setLastLoginType(0);
            superAdmin.setLastLoginIp("");
            final Date timeNow = Dates.getTimeNow();
            superAdmin.setLastLoginTime(timeNow);
            superAdmin.setHandleUser("平台系统");
            superAdmin.setCreateTime(timeNow);
            superAdmin.setUpdateTime(timeNow);

            adminUserRepository.insertSelective(superAdmin);

            final List<Long> roleIdList = Lists.asList(Long.valueOf(SystemConfigEnum.PLATFORM_ROLE_ID.getConfigValue()));
            userRoleService.insertUserRole(superAdmin.getAdminUserId(), roleIdList);

            log.info("===== ADMIN USER INIT SUCCESS, PASSWORD IS {} =====", defaultPassword);
        }

    }

    @Override
    public PageResult<AdminUserListDTO> selectUserPageResult(AdminUserQuery query) {
        PageResult<AdminUserEntity> pageResult = adminUserRepository.selectUserPageResult(query);
        List<AdminUserEntity> adminUserEntityList = pageResult.getRows();
        if (Lists.isNotEmpty(adminUserEntityList)) {
            List<AdminUserListDTO> userList = Beans.copyList(adminUserEntityList, AdminUserListDTO.class);
            this.setDeptName(userList, adminUserEntityList);
            this.setRoleName(userList, adminUserEntityList);
            return new PageResult<>(userList, pageResult.getTotal());
        }
        return PageResult.empty();
    }

    private void setRoleName(List<AdminUserListDTO> userList, List<AdminUserEntity> adminUserEntityList) {
        List<UserRoleDTO> userRoleList = userRoleService.selectAllUserRoleList();
        if (Lists.isEmpty(userRoleList)) {
            return;
        }
        List<Long> adminUserIdList = adminUserEntityList.stream().map(AdminUserEntity::getAdminUserId).collect(Collectors.toList());
        userList.forEach(user -> {
            List<UserRoleDTO> userRoles = userRoleList.stream()
                    .filter(role -> adminUserIdList.contains(role.getAdminUserId()) && role.getAdminUserId().equals(user.getAdminUserId()))
                    .collect(Collectors.toList());
            if (Lists.isNotEmpty(userRoles)) {
                String roleNames = userRoles.stream().map(UserRoleDTO::getRoleName).collect(Collectors.joining(","));
                user.setRoleName(roleNames);
            } else {
                user.setRoleName(Strings.EMPTY);
            }
        });
    }

    private void setDeptName(List<AdminUserListDTO> userList, List<AdminUserEntity> adminUserEntityList) {
        List<Long> deptIdList = adminUserEntityList.stream().map(AdminUserEntity::getDeptId).distinct().collect(Collectors.toList());
        DeptListQuery query = new DeptListQuery();
        query.setDeptIdList(deptIdList);
        List<DeptListDTO> deptList = deptService.selectDeptList(query);
        final List<Long> superAdminIdList = this.getSuperAdminIdList();
        userList.forEach(user -> {
            DeptListDTO dept = deptList.stream().filter(d -> d.getDeptId().equals(user.getDeptId())).findFirst().orElse(null);
            if (Objects.nonNull(dept)) {
                user.setDeptName(dept.getDeptName());
            }
            user.setSuperAdmin(superAdminIdList.contains(user.getAdminUserId()));
        });
    }



    @Override
    public void updateLastLoginInfo(Long adminUserId, String loginIp) {
        AdminUserEntity update = new AdminUserEntity();
        update.setAdminUserId(adminUserId);
        update.setLastLoginIp(loginIp);
        update.setLastLoginTime(Dates.getTimeNow());
        adminUserRepository.updateByPrimaryKeySelective(update);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveUser(AdminUserSaveDTO adminUser) {
        AdminUserEntity userEntity = Beans.copy(adminUser, AdminUserEntity.class);
        String handleUser = Contexts.getUserContext().getUserName();
        Date timeNow = Dates.getTimeNow();
        Long adminUserId;
        if (Longs.isNullOrZero(adminUser.getAdminUserId())) {
            this.checkUserName(userEntity);
            this.checkUserPhone(userEntity);
            userEntity.setUserType(Objects.isNull(adminUser.getUserType()) ? ContextUserType.ADMIN_PLATFORM.value() : adminUser.getUserType());
            userEntity.setHandleUser(handleUser);
            userEntity.setCreateTime(timeNow);
            userEntity.setPassword(PasswordUtil.encryptPassword(adminUser.getPassword()));
            userEntity.setIsDefaultPassword(Boolean.TRUE);
            adminUserRepository.insertSelective(userEntity);
            adminUserId = userEntity.getAdminUserId();
        } else {
            this.checkUserName(userEntity);
            this.checkUserPhone(userEntity);
            adminUserId = adminUser.getAdminUserId();
            userEntity.setHandleUser(handleUser);
            userEntity.setUpdateTime(timeNow);
            adminUserRepository.updateByPrimaryKeySelective(userEntity);
            userRoleService.deleteUserRole(adminUserId);
            if (Objects.equals(StatusEnum.disable.value(), userEntity.getStatus())) {
                adminTokenService.delLoginToken(adminUserId);
            }
        }
        userRoleService.insertUserRole(adminUserId, adminUser.getRoleIdList());
        return adminUserId;
    }

    @Override
    public boolean isSuperAdmin(Long adminUserId) {
        List<Long> adminUserIdList = getSuperAdminIdList();
        return Lists.contains(adminUserIdList, adminUserId);
    }

    private List<Long> getSuperAdminIdList() {
        return configService.getSuperAdminUserIdList();
    }

    @Override
    public void checkUserAllowed() {
        Long userId = Contexts.getUserContext().getUserId();
        if (!this.isSuperAdmin(userId)) {
            throw Ex.business("只允许超级管理员执行该操作");
        }
    }

    @Override
    public void resetPassword(Long adminUserId, String password) {
        log.info("重置用户密码, adminUserId: {}, password: {}", adminUserId, password);
        AdminUserEntity update = buildUpdateCommonParam(adminUserId);
        update.setPassword(PasswordUtil.encryptPassword(password));
        update.setIsDefaultPassword(Boolean.FALSE);
        adminUserRepository.updateByPrimaryKeySelective(update);
        adminTokenService.delLoginToken(adminUserId);
    }

    @Override
    public void changeStatus(Long adminUserId, Integer status) {
        if (!Lists.contains(Lists.asList(StatusEnum.disable.value(), StatusEnum.normal.value()), status)) {
            throw Ex.business("非法状态");
        }
        AdminUserEntity update = buildUpdateCommonParam(adminUserId);
        update.setStatus(status);
        adminUserRepository.updateByPrimaryKeySelective(update);

        if (Objects.equals(StatusEnum.disable.value(), status)) {
            adminTokenService.delLoginToken(adminUserId);
        }
    }

    @Override
    public void grantRole(Long adminUserId, List<Long> roleIdList) {
        userRoleService.deleteUserRole(adminUserId);
        userRoleService.insertUserRole(adminUserId, roleIdList);
    }

    @Override
    public AdminUserEntity selectUserName(Integer userType, String userName) {
        AdminUserQuery query = new AdminUserQuery();
        query.setUserName(userName);
        query.setUserType(userType);
        return adminUserRepository.selectOne(query);
    }

    @Override
    public AdminUserSaveDTO getUserDetail(Long adminUserId) {
        AdminUserEntity adminUserEntity = adminUserRepository.selectByPrimaryKey(adminUserId);
        AdminUserSaveDTO userDetail = Beans.copy(adminUserEntity, AdminUserSaveDTO.class);
        userDetail.setRoleIdList(userRoleService.selectUserRoleIdList(adminUserId));
        return userDetail;
    }

    /**
     * 用户名称唯一性校验
     */
    private void checkUserName(AdminUserEntity userEntity) {
        AdminUserQuery query = new AdminUserQuery();
        query.setUserName(userEntity.getUserName());
        if (Longs.notNullAndZero(userEntity.getAdminUserId())) {
            query.setIdNotEqual(userEntity.getAdminUserId());
        }
        if (Objects.nonNull(adminUserRepository.selectOne(query))) {
            throw Ex.business("重复的用户名");
        }
    }
    /**
     * 手机号唯一性校验
     */
    private void checkUserPhone(AdminUserEntity userEntity) {
        AdminUserQuery query = new AdminUserQuery();
        query.setPhoneNumber(userEntity.getPhoneNumber());
        if (Longs.notNullAndZero(userEntity.getAdminUserId())) {
            query.setNotInUserIdIdList(Lists.asList(userEntity.getAdminUserId()));
        }
        if (Objects.nonNull(adminUserRepository.selectOne(query))) {
            throw Ex.business("重复的手机号");
        }
    }

    private AdminUserEntity buildUpdateCommonParam(Long adminUserId) {
        AdminUserEntity update = new AdminUserEntity();
        update.setAdminUserId(adminUserId);
        update.setUpdateTime(Dates.getTimeNow());
        update.setHandleUser(Contexts.getUserContext().getUserName());
        return update;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(Long adminUserId, String oldPassword, String password) {
        AdminUserEntity adminUserEntity = adminUserRepository.selectByPrimaryKey(adminUserId);
        if (Objects.isNull(adminUserEntity)) {
            throw Ex.business("用户不存在");
        }
        if (!PasswordUtil.matchesPassword(oldPassword, adminUserEntity.getPassword())) {
            throw Ex.business("修改密码失败，旧密码错误");
        }
        if (PasswordUtil.matchesPassword(password, adminUserEntity.getPassword())) {
            throw Ex.business("新密码不能与旧密码相同");
        }
        AdminUserEntity update = new AdminUserEntity();
        update.setAdminUserId(adminUserId);
        update.setPassword(PasswordUtil.encryptPassword(password));
        update.setIsDefaultPassword(Boolean.FALSE);
        update.setHandleUser(Contexts.getUserContext().getUserName());
        update.setUpdateTime(Dates.getTimeNow());
        adminUserRepository.updateByPrimaryKeySelective(update);

        adminTokenService.delLoginToken(adminUserId);
    }

    @Override
    public PageResult<AdminUserListDTO> selectUnAllocatedList(AdminUserQuery query) {
        List<Long> userIdList = userRoleService.selectUserIdList(query.getRoleId());
        query.setNotInUserIdIdList(userIdList);
        query.setUserType(ContextUserType.ADMIN_PLATFORM.getValue());
        PageResult<AdminUserEntity> pageResult = adminUserRepository.selectUserPageResult(query);
        return PageResult.of(pageResult, AdminUserListDTO.class);
    }

    @Override
    public PageResult<AdminUserListDTO> selectAllocatedList(AdminUserQuery query) {
        List<Long> userIdList = userRoleService.selectUserIdList(query.getRoleId());
        if (Lists.isNotEmpty(userIdList)) {
            query.setUserIdIdList(userIdList);
        } else {
            query.setUserIdIdList(Lists.asList(0L));
        }
        PageResult<AdminUserEntity> pageResult = adminUserRepository.selectUserPageResult(query);
        return PageResult.of(pageResult, AdminUserListDTO.class);
    }

    @Override
    @Transactional
    public void deleteUser(Long adminUserId) {
        AdminUserEntity adminUserEntity = adminUserRepository.selectByPrimaryKey(adminUserId);
        if (Objects.isNull(adminUserEntity)) {
            throw Ex.business("用户不存在");
        }
        if (this.isSuperAdmin(adminUserId)) {
            throw Ex.business("当前用户不能删除");
        }
        AdminUserEntity update = new AdminUserEntity();
        update.setAdminUserId(adminUserId);
        update.setDelFlag(DelFlagEnum.delete.getValue());
        update.setUpdateTime(Dates.getTimeNow());
        update.setHandleUser(Contexts.getUserContext().getUserName());
        adminUserRepository.updateByPrimaryKeySelective(update);
        adminTokenService.delLoginToken(adminUserId);
    }

    @Override
    @Transactional
    public Long createProxyUserAccount(String proxyName, String contactUser, String contactPhone) {
        AdminUserQuery query = new AdminUserQuery();
        query.setUserName(contactPhone);
        final AdminUserEntity adminUserEntity = adminUserRepository.selectOne(query);
        if (Objects.nonNull(adminUserEntity)) {
            throw Ex.business("登录账号{}已存在", contactPhone);
        }
        AdminUserSaveDTO adminUser = new AdminUserSaveDTO();
        adminUser.setUserName(contactPhone);
        adminUser.setNickName(contactUser);
        adminUser.setPhoneNumber(contactPhone);
        adminUser.setUserType(ContextUserType.ADMIN_PROXY.value());
        adminUser.setEmail(Strings.EMPTY);
        adminUser.setSex(Numbers.INTEGER_ZERO);
        adminUser.setStatus(StatusEnum.normal.value());
        adminUser.setRoleIdList(Lists.asList(100005L));
        adminUser.setRemark(Strings.format("代理商{}的平台账户", proxyName));
        adminUser.setPassword(adminUser.getPhoneNumber().substring(5));
        return this.saveUser(adminUser);
    }

    @Override
    public List<SimpleAdminUserDTO> selectSimpleAdminUser(List<Long> deptIdList, String keyword) {
        AdminUserQuery query = new AdminUserQuery();
        query.setDeptIdList(deptIdList);
        query.setKeyword(keyword);
        query.setStatus(StatusEnum.normal.value());
        query.setPage(1);
        query.setSize(100);
        return Beans.copyList(adminUserRepository.selectUserList(query), SimpleAdminUserDTO.class);
    }

    @Override
    public Long createPartnerUserAccount(CreateAdminUserAccount partnerAdminUser) {
        AdminUserQuery query = new AdminUserQuery();
        query.setUserName(partnerAdminUser.getUserName());
        final AdminUserEntity adminUserEntity = adminUserRepository.selectOne(query);
        if (Objects.nonNull(adminUserEntity)) {
            throw Ex.business("登录账号{}已存在", partnerAdminUser.getUserName());
        }
        AdminUserSaveDTO adminUser = new AdminUserSaveDTO();
        adminUser.setUserName(partnerAdminUser.getUserName());
        adminUser.setNickName(partnerAdminUser.getNickName());
        adminUser.setPhoneNumber(partnerAdminUser.getPhoneNumber());
        final String PARTNER_DEPT_ID = configService.getStringConfig(BizConfigEnum.PARTNER_DEPT_ID.getConfigKey());
        adminUser.setDeptId(Long.valueOf(PARTNER_DEPT_ID));
        adminUser.setUserType(ContextUserType.ADMIN_PLATFORM.value());
        adminUser.setEmail(Strings.EMPTY);
        adminUser.setSex(Numbers.INTEGER_ZERO);
        adminUser.setStatus(StatusEnum.normal.value());
        final String PARTNER_ROLE_ID = configService.getStringConfig(BizConfigEnum.PARTNER_ROLE_ID.getConfigKey());
        adminUser.setRoleIdList(Lists.asList(Long.valueOf(PARTNER_ROLE_ID)));
        adminUser.setPassword(partnerAdminUser.getPhoneNumber().substring(5));
//        adminUser.setAllowedLoginTypeList(Lists.asList(AdminLoginTypeEnum.ACCOUNT_LOGIN.value()));
        adminUser.setRemark(partnerAdminUser.getRemark());
//        adminUser.setSuperAdmin(Boolean.FALSE);
        adminUser.setExtendInfo(Jsons.toJsonString(partnerAdminUser.getExtendInfo()));
        return this.saveUser(adminUser);
    }

    @Override
    public List<SimpleAdminUserDTO> selectSimpleAdminUser(List<Long> adminUserIdList) {
        AdminUserQuery query = new AdminUserQuery();
        query.setUserIdIdList(adminUserIdList);
        query.setStatus(StatusEnum.normal.value());
        query.setPage(1);
        query.setSize(100);
        return Beans.copyList(adminUserRepository.selectUserList(query), SimpleAdminUserDTO.class);
    }
}
